﻿// JScript source code

var subArray = function (array, start, end) {
    var r = [];
    for (var i = start; i < array.length && i < end; i++) {
        r.push(array[i]);
    }
    return r;
}

var bind = function (fn, scope) {
    return function () {
        return fn.apply(scope, arguments);
    }
}

var __applyNewCache__ = {};
var applyNew = function (argvLen) {

    var fn = __applyNewCache__[argvLen];
    if (!fn) {
        var code = "(function(){return function(fn, argv) { return new fn(";
        for (var i = 0; i < argvLen; i++) {
            if (i == 0) {
                code += "argv[" + i + "]"
            } else {
                code += ", argv[" + i + "]"
            }
        }
        code += ")};})()";
        fn = eval(code);
        __applyNewCache__[argvLen] = fn;
    }
    return fn;
}

var PureCallException = {
    message: "call pure virtual method!"
}
// 扩展
var extend = function (superClass, constructor) {

    var cons = function () {

        var isSuperCalled = null;
        var outterThis = this;
        var virtualCall = null;
        var superIns = null;

        var wrapper = function () {
            // 构造父类实例，并且绑定函数
            superIns = applyNew(arguments.length)(superClass, arguments);
            for (var propName in superIns) {
                if (typeof superIns[propName] == "function") {
                    outterThis[propName] = bind(superIns[propName], superIns);
                }
            }

            superIns.virtual = function (name) {
                var v = outterThis.virtual(name);
                if (!v && typeof superIns[name] == "function") {
                    v = superIns[name];
                }
                return v;
            }

            isSuperCalled = true;
            
            return superIns;
        }
        

        // 调用子类的构造方法
        var list = [];
        for (var i = 0; i < arguments.length; i++) {
            list.push(arguments[i]);
        }
        
        this.base = wrapper;
        constructor.apply(this, list);
        delete this.base;

        this.virtual = function (name) {
            if (typeof this[name] == "function") {
                return this[name];
            }
        }

        if (!isSuperCalled) {
            throw "must call constructor";
        }
    }
    return cons;
}



Super = extend(function () { }, function (name, value) {

    this.base(name, value);

    var list = [];

    this.add = function (value) {
        list.push("super:" + value);
    }

    this.add2 = function (value) {
        list.push("super:" + value);
        this.virtual("overrideFn")("cool!");
        this.virtual("overrideFn")("cool!");
    }

    this.callPure = function () {
        this.virtual("pure", "cool!")("cool!");
    }

    this.toText = function () {
        return list.join(",");
    }
});

Sub2 = extend(Super, function (name, value) {

    this.base(name, value);

});

Sub = extend(Sub2, function (name, value) {

    var base = this.base(name, value);

    var list = [];

    this.add = function (value) {
        list.push("Sub:" + value);
        base.add(value);
    }

    this.toText2 = function () {
        return list.join(",");
    }

    this.overrideFn = function (str) {
        alert(str);
    }
});

debugger;
var sub = new Sub("sub", 100);
sub.add("first");
sub.add2("second");

var r1 = sub.toText();
var r2 = sub.toText2();
alert("r1=" + r1 + ",r2=" + r2);

sub.callPure();